/****************************************************************
 * I am the AC 130 vs Pirate game. I allow the user to control an 
 * AC130 gunship in the hunt for Modern day pirates. The player  
 * will be allowed to roam free across a section of ocean/coastline.  
 * In the water there will be four types of vessels: Merchant  
 * ships that the player must protect, Pirate ships that the player  
 * must identify and destroy, Fishing boats that look like Pirate  
 * ships that the player must not destroy, and Friendly Navy ships  
 * that can capture pirates for extra points. Time permitting there  
 * may also be ground targets to attack. 
 *
 * Key elements of this project will be the Player/AC130, the Ships,  
 * the ShipAI system, the collision grid, the debris controller, the  
 * Ground/Water, Clouds, and scoring system. This project will make  
 * use of an external text file to store useful game parameters,  
 * thus allowing us to play balance the game without recompiling  
 * the executable. 
 *****************************************************************
 * I am the Game Play Screen. I contain all world objects that are 
 * needed to maintain the game play. The player will be spending most
 * of their time on this screen. External screens will have te ability
 * to communicate settings to this screen via the GamData Class.
 *****************************************************************/

#include "scGamePlay.h"
#include "BulletCtrl.h"
#include <math.h>

/// I am the constructor. I create all objcets native to this screen
scGamePlay::scGamePlay(){
	myGround = new Ground;
	myPlane = new Plane;
	myBulletCtrl = new BulletCtrl;
	myCrashBin = new CrashBin;
	myShipCtrl = new ShipCtrl;
	myScreenType = stGamePlay;

	isLdown = isRdown = false;

		// edit values
	dx = dy = 0;
	editMode = 2;
	editIndex = 0;
		// these are the world point references.
	worldMouseCur = new Point;
	worldMouseDn = new Point;
}
scGamePlay::~scGamePlay(){
	delete(myGround);
	delete(myPlane);
	delete(myBulletCtrl);
	delete(myShipCtrl);
}

// I am the initilization function. I accept the external GameData
// class and do the one time processing that requires a GameData 
// Pointer like load images from hash table paths. I am also
// responsible for passing the GameData pointer to this screen's
// internal components
void scGamePlay::Init(GameData *exGd){
	gd = exGd;
	myCrashBin->Init(gd);
	myCam = gd->myCam;
	myGround->Init(exGd, myCrashBin);
	myBulletCtrl->Init(exGd, myCrashBin);
	myPlane->Init(exGd, myBulletCtrl);
	myShipCtrl->Init(exGd, myBulletCtrl, myCrashBin);

	zoomRate = gd->GetNum("scrZoomRate");
}

/// I am the screen start function. I run the processes that need to
/// be run after this screen gets control from another screen.
void scGamePlay::OnStart(){
	
}

/// I am the screen close function. I run the processes that need to
/// be run before this screen passes control from another screen.
void scGamePlay::OnClose(){}

/// I am the mouse down event handeler. I get the mouse's position in
/// the screen as well as the button index that was pressed. 
void scGamePlay::OnMouseDn(int mouseX, int mouseY, int bt){
	if(bt == 1)isLdown = true;
	if(bt == 2)isRdown = true;

	if(editMode == 3){
		if(bt == 1){
			worldMouseDn->x = gd->myCam->STWx(gd->mouseX);
			worldMouseDn->y = gd->myCam->STWy(gd->mouseY);
		}
	}
}

/// I am the mouse up event handeler. I get the mouse's position in
/// the screen as well as the button index that was pressed. 
/// go to main menu
void scGamePlay::OnMouseUp(int mouseX, int mouseY, int bt){
	if(bt == 1)isLdown = false;
	if(bt == 2)isRdown = false;

	if(editMode == 2 && bt == 2){	// ground edit sellect on right button up
		editIndex = myGround->PickTile(gd->mouseX, gd->mouseY);
		sprintf(gd->debugTxt, "Ground Tile Index selected; %d",editIndex );
	}
}


/// I am the key down event handeler. I pass the allegro key code of 
/// the key that was pressed in the latest update cycle.
void scGamePlay::OnKeyDn(int keyCode){
	// use F1-F4 keys to chainge edit mode
	if(keyCode == KEY_F1){ 
		editMode = 1;	
		editIndex = 0;
		myPlane->center->Copy(myCam->center);
		sprintf(gd->debugTxt, "Now in Game play Mode" );
	}
	if(keyCode == KEY_F2){ 
		editMode = 2;	
		editIndex = 0;
		sprintf(gd->debugTxt, "Now in Ground Tile edit Mode" );
	}
	if(keyCode == KEY_F3){ 
		editMode = 3;	
		editIndex = 0;
		sprintf(gd->debugTxt, "Now in Static Building edit Mode" );
	}

		// don't load map as program start will do it for us
	//if(key[KEY_F7]){ 
	//	myGround->LoadMap(gd->GetStr("mapEdit");
	//}
	if(keyCode == KEY_F8){ 
		myGround->SaveMap(gd->GetStr("mapEdit"));
	}

		// context sensitive opperatoins
	if(editMode == 2){	// ground tile edit
		int worldMouseX = gd->myCam->STWx(gd->mouseX);
		int worldMouseY = gd->myCam->STWy(gd->mouseY);
		if(keyCode == KEY_SPACE){// eye droper the current tile
			editIndex = myGround->GetTile(myGround->GetMapX(worldMouseX),
				myGround->GetMapY(worldMouseY));
			sprintf(gd->debugTxt, "Ground Tile Eyedrop Selected; %d",editIndex );
		}
	}
	if(editMode == 1){
			// debug spawn 
		if(keyCode == KEY_BACKSPACE){
			myShipCtrl->Spawn(myPlane->center,0,-myPlane->angle);
		}
	}

	
}

/// I am the key up event handeler. I pass the allegro key code of 
/// the key that was released in the latest update cycle.
/// go to main menu
void scGamePlay::OnKeyUp(int keyCode){


}

/// I am the update function. I get the screen coordinates of the mouse
/// on a regular basis. All positional/animation updates should get 
/// processed here 
void scGamePlay::Update(){
		// do special case editing
	if(UpdateEdit()) return;

	// register all game objects in the crash bin
	myCrashBin->ClearRegister();
	myCrashBin->Register(tpBinType::btPlayer, 0, 
		myPlane->center->x, myPlane->center->y);
	
	// todo register buildings
	myBulletCtrl->RegisterBin();
	myShipCtrl->Register();

	// set camera relative to plane
	myPlane->SetCamera(myCam);
	//myCam->center->Copy(myPlane->center);
		// set aim point to the mouse location in screen
	myPlane->aim->x = myCam->STWx(gd->mouseX),
	myPlane->aim->y = myCam->STWy(gd->mouseY);

		// update game play elements
		// process 
	myPlane->inUp = key[KEY_W];
	myPlane->inDown = key[KEY_S];
	myPlane->inLeft = key[KEY_A];
	myPlane->inRight = key[KEY_D];
	myPlane->inLstrafe = key[KEY_Q];
	myPlane->inRstrafe = key[KEY_E];
	myPlane->inShoot = isLdown;
		// use Right mouse as zoom rate controll
	if(isRdown){
		myCam->zoom -= zoomRate; 
	}else{
		myCam->zoom += zoomRate;
	}

	myPlane->Update();
	myBulletCtrl->Update();
	myBuildingCtrl->Update();
	myShipCtrl->Update();
}

bool scGamePlay::UpdateEdit(){
	// default all controlls to non edit mode,
	// they will be set active in this function.
	myGround->isEdit = false;
	

	if( editMode ==1) return false;
	// special case input based on edit mode
	if(editMode > 1){
		float ddelta = 4.0;	// acceleration
		float dampen = 0.90;	// speed dampening
		if(key[KEY_W]) dy -= ddelta;
		if(key[KEY_S]) dy += ddelta;
		if(key[KEY_A]) dx -= ddelta;
		if(key[KEY_D]) dx += ddelta;
		if(key[KEY_R]) myCam->zoom += 0.1;
		if(key[KEY_F]) myCam->zoom -= 0.1;
			// slow down
		dx *= dampen;
		dy *= dampen;
			// move position
		myCam->center->x += dx;
		myCam->center->y += dy;
	}
		
		// exicute special ground editing functions
	if(editMode == 2){
		int worldMouseX = gd->myCam->STWx(gd->mouseX);
		int worldMouseY = gd->myCam->STWy(gd->mouseY);
		myGround->isEdit = true;
		if(isLdown){	// start painting
			myGround->SetTile(myGround->GetMapX(worldMouseX),
				myGround->GetMapY(worldMouseY), editIndex);
				// write action to debug
			sprintf(gd->debugTxt, "Set map Cooinate X:%d Y:%d To Tile#:%d", 
				myGround->GetMapX(worldMouseX),
				myGround->GetMapY(worldMouseY), editIndex);
		}
	}

		// I am the edit section
	if(editMode == 3){
		if(isLdown){
			worldMouseCur->x = gd->myCam->STWx(gd->mouseX);
			worldMouseCur->y = gd->myCam->STWy(gd->mouseY);
			myBuildingCtrl->PlaceBldg(worldMouseCur, worldMouseCur, editIndex);
		}
	}

			
// enforce map bounds on camera
	if(myCam->center->x < 0) myCam->center->x = 0;
	if(myCam->center->y < 0) myCam->center->y = 0;
	if(myCam->center->x > myGround->map->w*myGround->tileW) 
		myCam->center->x = myGround->map->w*myGround->tileW;
	if(myCam->center->y > myGround->map->h*myGround->tileH) 
		myCam->center->y = myGround->map->h*myGround->tileH;
}

/// I am the draw function. I get the back buffer passed in as 
/// an argument. I draw this screen's data to the back buffer once
/// per update cycle
void scGamePlay::Draw(BITMAP * myScreen){
	myGround->DrawWater(myCam);

	myGround->DrawGround(myCam);
	myShipCtrl->Draw(myCam);
	myBuildingCtrl->Draw(myCam);
	myBulletCtrl->Draw(myCam);
		//draw plane above all other things
	myPlane->DrawPlane(myCam);
		// activate world to screen drawing
	
	myCam->RendWorld();
		
	

		// draw overlay
	if(editMode == 2){
			// draw current tile
		rectfill(myCam->screen,0,20,68,88, makecol(0,255,255));
		stretch_blit(myGround->tile[editIndex],myCam->screen, 0,0,
				myGround->tile[editIndex]->w,myGround->tile[editIndex]->h,
				 2, 22,
				64,64);
			// draw map
		stretch_blit(myGround->map,myCam->screen, 0,0,
				myGround->map->w,myGround->map->h,
				 myCam->screen->w - 128, 0,
				128,128);
			//draw location on Map
		int mlocx = myGround->GetMapX(myCam->center->x)*128/myGround->map->w;
		int mlocy = myGround->GetMapY(myCam->center->y)*128/myGround->map->h;
		if( isRdown)myGround->DrawTilePick(myCam, editIndex);
	}

		// blit Camerascreen to myscreen
	//blit(myCam->screen, myScreen,0,0,0,0,myScreen->w,myScreen->h);
		// draw cursor
	line(myScreen, mouse_x -10, mouse_y, mouse_x+10, mouse_y, makecol(255,0,0));
	line(myScreen, mouse_x , mouse_y-10, mouse_x, mouse_y+10, makecol(255,0,0));


}